#include "win_socket.h"



QELOG_DOMAIN("win-socket");



qe_ret win_socket_init(win_socket *sock, int proto, const char *address, qe_u16 port)
{
    WSAStartup(MAKEWORD(2, 2), &sock->ws);

    if (proto == WIN_SOCKET_UDP) {
        sock->s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    } else {
        sock->s = socket(AF_INET, SOCK_DGRAM, IPPROTO_TCP);
    }

    if (!sock->s) {
        qe_error("socket create error");
        return qe_err_common;
    }

    sock->server_addr.sin_family = AF_INET;
    if (address) {
        sock->server_addr.sin_addr.s_addr = inet_addr(address);
    } else {
        sock->server_addr.sin_addr.s_addr = inet_addr(INADDR_ANY);
    }
    
    sock->server_addr.sin_port = htons(port);

    sock->client_addr_len = sizeof(sock->client_addr);

    qe_debug("udp socket init with %s:%d", address, port);
    
    return qe_ok;
}

qe_ret win_socket_bind(win_socket *sock)
{
    int r;

    r = bind(sock->s, (struct sockaddr *)&sock->server_addr, 
        sizeof(sock->server_addr));
    if (r < 0) {
        qe_error("socket bind error");
        return qe_err_common;
    }

    return qe_ok;
}

qe_ret win_socket_listen(win_socket *sock, int backlog)
{
    int r;

    r = listen(sock->s, backlog);
    if (r < 0) {
        qe_error("socket listen error:%d", r);
        return qe_err_common;
    }

    return qe_ok;
}

qe_ret udp_socket_send(win_socket *sock, char *buf, int size)
{
    int n;

    n = sendto(sock->s, buf, size, 0, 
            (struct sockaddr *)&sock->client_addr, 
            sizeof(sock->client_addr));
    if (n < 0) {
        udp_error("send error");
        return qe_err_send;
    }

    if (n != size) {
        udp_warning("send size error, %d %d", n, size);
    }

    return qe_ok;
}

qe_ret udp_socket_recv(udp_socket *sock, char *buf, int size, int *rxsize)
{
    int n;

    n = recvfrom(sock->s, buf, size, 0, 
            (struct sockaddr *)&sock->client_addr,
            &sock->client_addr_len);
    if (n < 0) {
        udp_error("recv error");
        return qe_err_common;
    }

    *rxsize = n;

    return qe_ok;
}

void udp_socket_exit(udp_socket *sock)
{
    if (sock->s) {
        closesocket(sock->s);
        WSACleanup();
        udp_debug("udp socket exit");
    }
}